#pragma once
#include <functional>
#include <atomic>
#include <memory>
#include <vector>
#include <mutex>

#include "noncopyable.h"
#include "Timestamp.h"
#include "CurrentThread.h"

class Poller;
class Channel;

class EventLoop : noncopyable
{
public:
    using Functor = std::function<void()>;

    EventLoop();
    ~EventLoop();

    // 开始事件循环
    void loop();
    // 退出事件循环
    void quit();

    Timestamp pollReturnTime() const {return pollReturnTime_; }

    // 在当前loop中执行
    void runInLoop(Functor cb);
    // 将cb放入到队列中，唤醒loop所在的线程，执行cb
    void queueInLoop(Functor cb);

    // 唤醒loop所在的线程
    void weakup();

    void updateChannel(Channel* channel);
    void removeChannel(Channel* channel);
    bool hasChannel(Channel* channel);

    // 判断EventLoop是否在自己的线程里面
    bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); }

private:
    void handleRead();
    void doPendingFunctors();

    using ChannelList = std::vector<Channel*>;
    std::atomic<bool> looping_;      // 底层通过CAS实现原子性
    std::atomic<bool> quit_;         // 标识退出loop循环
    const pid_t threadId_;           // 当前eventloop所在的线程
    Timestamp pollReturnTime_;       // 表示poll退出的时间
    std::unique_ptr<Poller> poller_; // 用来监听channel上所发生的事件

    // MainReactor获取到channel后，通过轮询选择一个subReactor来处理channel
    // 通过系统调用eventfd来创建
    int weakupFd_;
    std::unique_ptr<Channel> weakupChannel_;

    ChannelList activeChannels_;
    Channel *currentActiveChannel_;

    std::atomic<bool> callingPendingFunctors_; // 标识当前loop是否需要执行回调函数
    std::vector<Functor> pendingFunctors_;     // 存储loop需要执行的所有回调函数
    std::mutex mutex_;                         // 互斥锁，用来保护上面vector容器的线程安全问题
};
